<template>
  <div id="onekeypack">
    <div style="width: 100%;margin: 0 auto;">
      <div class="title-container">
        <el-button
          icon="el-icon-circle-plus-outline"
          type="primary"
          size="small"
          @click="importPack"
        >导入模板
        </el-button>
        <h3>打包记录</h3>
        <el-tag
          size="mini"
          effect="dark"
          class="right-tag"
        >
          <i class="el-icon-folder" style="color: #E5E4EB">打包根目录：</i>
          <span style="font-weight: bolder">{{ compileRootPath }}</span>
        </el-tag>
      </div>
      <el-table
        ref="recordTblRef"
        :data="recordTblData"
        border
        style="width: 100%"
        max-height="760"
        cell-class-name="cellClass"
        header-cell-class-name="headerClass"
      >
        <el-table-column
          v-for="item in recordHeaders"
          :key="item.prop"
          :prop="item.prop"
          :label="item.label"
          :width="item.width"
        >
          <template slot-scope="scope">
            <div v-if="item.isLink">
              <el-button type="text" size="small" @click="lookDetail(item.prop, scope.row)">{{
                scope.row[item.prop]
              }}
              </el-button>
            </div>
            <span v-else-if="item.isStatus">
              <el-tooltip
                v-if="scope.row[item.prop] === '1'"
                class="item"
                effect="dark"
                content="任务执行中"
                placement="top-start"
              >
                <i class="el-icon-loading" style="color: #409eff;" />
              </el-tooltip>
              <el-tooltip
                v-else-if="scope.row[item.prop] === '2'"
                class="item"
                effect="dark"
                content="任务执行成功"
                placement="top-start"
              >
                <i class="el-icon-circle-check" style="color: #67C23A;" />
              </el-tooltip>
              <el-tooltip
                v-else-if="scope.row[item.prop] === '4'"
                class="item"
                effect="dark"
                content="任务等待中"
                placement="top-start"
              >
                <i class="el-icon-time" style="color: #E6A23C;" />
              </el-tooltip>
              <el-tooltip
                v-else-if="scope.row[item.prop] === '3'"
                class="item"
                effect="dark"
                content="任务执行失败"
                placement="top-start"
              >
                <i class="el-icon-circle-close" style="color: #f56c6c;" />
              </el-tooltip>
              <el-tooltip
                v-else
                class="item"
                effect="dark"
                content="任务初始化"
                placement="top-start"
              >
                <i class="iconfont icon-xitongchushihua" style="color: #909399;" />
              </el-tooltip>
            </span>
            <span v-else>{{ scope.row[item.prop] }}</span>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        style="float:right;"
        :current-page="currentPage"
        :page-sizes="[10, 20, 50, 100]"
        :page-size="pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="totalSize"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />

      <el-dialog
        :title="lookTitle"
        :visible.sync="dialogVisible"
        width="40%"
        :close-on-click-modal="false"
      >
        <el-table
          ref="detailTblRef"
          :data="detailTblData"
          border
          style="width: 100%"
          max-height="400"
          cell-class-name="cellClass"
          header-cell-class-name="headerClass"
        >
          <el-table-column
            v-for="item in detailHeader"
            :key="item.prop"
            :prop="item.prop"
            :label="item.label"
            :width="item.width"
          >
            <template slot-scope="scope">
              <div v-if="item.isOp">
                <el-button type="text" size="small" @click="logDetail(scope.row)">日志详情</el-button>
              </div>
              <span v-else>{{ scope.row[item.prop] }}</span>
            </template>
          </el-table-column>
        </el-table>

        <el-dialog
          title="日志详情"
          :visible.sync="logVisible"
          width="40%"
          :close-on-click-modal="false"
          append-to-body
        >
          <el-scrollbar
            ref="scrollbar"
            style="height: 500px;margin: 20px"
            @scroll="handleScroll"
          >
            <div
              ref="logContent"
              class="log-content"
              v-html="formattedLogs"
            />
          </el-scrollbar>
        </el-dialog>
      </el-dialog>
    </div>

    <el-dialog
      title="一键打包模板导入"
      :visible.sync="oneKeyVisible"
      :close-on-click-modal="false"
      width="30%"
    >
      <div style="position: relative">
        <el-button
          ref="downloadBtnRef"
          size="small"
          type="text"
          style="float: right;"
          @click="downloadTemplate"
        >
          下载模板
        </el-button>
        <RbUpload
          :file-list="fileList"
          accept=".xlsx, .xls"
          tip="只能上传 xlsx/xls 格式文件，且不超过5MB"
          @on-success="handleSuccess"
          @on-process="handleProcess"
        />
      </div>
    </el-dialog>
  </div>
</template>

<script>
import RbUpload from '@/layout/components/RbUpload.vue'
import { getOnePackRecords, oneKeyPack } from '@/api/task'
import { getBuildLogById, getCompsByLogIds } from '@/api/project'

export default {
  name: 'OneKeyPack',
  components: { RbUpload },
  data() {
    return {
      recordHeaders: [{
        prop: 'taskId',
        label: '任务ID'
      }, {
        prop: 'packName',
        label: '压缩包名（不含后缀）'
      }, {
        prop: 'totalNum',
        label: '构建总数'
      }, {
        prop: 'waitNum',
        label: '执行中数量'
      }, {
        prop: 'successNum',
        label: '成功数量',
        isLink: true
      }, {
        prop: 'failureNum',
        label: '失败数量',
        isLink: true
      }, {
        prop: 'operator',
        label: '操作人'
      }, {
        prop: 'executionTime',
        label: '执行时间'
      }, {
        prop: 'status',
        label: '任务状态',
        isStatus: true,
        width: '100px'
      }],
      recordTblData: [],
      lookTitle: '成功详情',
      dialogVisible: false,

      // 查看详情弹窗
      detailHeader: [{
        prop: 'componentName',
        label: '组件名称'
      }, {
        prop: 'branch',
        label: '分支'
      }, {
        prop: 'tag',
        label: '组件Tag'
      }, {
        prop: 'supervisor',
        label: '负责人'
      }, {
        prop: 'operation',
        label: '操作',
        isOp: true,
        width: '100px'
      }],
      detailTblData: [],
      logVisible: false,
      logContent: '',
      oneKeyVisible: false,
      fileList: [],
      loading: {},
      packSubs: {},

      // 分页信息
      currentPage: 1,
      pageSize: 10,
      totalSize: 0,

      // 打包根目录
      compileRootPath: ''
    }
  },
  computed: {
    formattedLogs() {
      return this.highLightErrors(this.logContent)
    }
  },
  async created() {
    // 初始化websocket
    const stompClient = await this.$store.dispatch('websocket/initWebSocket')
    const projectInfo = await this.$store.dispatch('project/changeInnerProjectId')
    console.log(projectInfo)
    this.compileRootPath = projectInfo.compileRootPath
    // 订阅环境状态 Topic
    this.packSubs = stompClient.subscribe(`/user/${this.$store.getters.userId}/topic/project/` +
      projectInfo.projectId + '/oneKeyPack', (message) => {
      const data = JSON.parse(message.body)
      data.status = data.status + ''
      const rowIndex = this.recordTblData.findIndex(item => item.taskId === data.taskId)
      // 替换行数据
      this.$set(this.recordTblData, rowIndex, data)
    })
  },
  mounted() {
    this.initOnePackData()
  },
  beforeDestroy() {
    this.packSubs.unsubscribe()
  },
  methods: {
    initOnePackData() {
      this.recordTblData = []
      getOnePackRecords({ currentPage: this.currentPage, pageSize: this.pageSize }).then(res => {
        const records = res.data
        if (records && records.length > 0) {
          records.forEach(item => {
            item.status = item.status + ''
            this.recordTblData.push(item)
          })
          this.totalSize = res.totalSize
        }
      }).catch(err => {
        console.error(err)
        this.$message.error('数据初始化失败')
      })
    },

    escapeHtml(unsafeText) {
      return unsafeText
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#039;')
    },
    // 错误行判断逻辑
    isErrorLine(line) {
      return line.match(/(ERROR|BUILD FAILURE|FAILED|ERR|Exception)/i)
    },
    highLightErrors(content) {
      if (!content) {
        return ''
      }
      return content.split('\n').map(line => {
        // 转义 HTML 特殊字符
        const escapedLine = this.escapeHtml(line)
        // 错误检测逻辑
        if (this.isErrorLine(escapedLine)) {
          return `<span style="color: #f56c6c; font-weight: 600">${escapedLine}</span><br/>`
        }
        return `${escapedLine}<br/>`
      }).join('')
    },

    // 导入打包
    importPack() {
      this.oneKeyVisible = true
      this.fileList = []
    },

    handleSuccess(buildFile) {
      oneKeyPack({ fileId: buildFile.id }).then(res => {
        this.$message.success('导入成功，已进入后台处理，请留意打包记录。')
        this.initOnePackData()
        this.loading.close()
        this.oneKeyVisible = false
      }).catch(err => {
        console.error(err)
        this.$message.error('导入失败')
        this.loading.close()
      })
    },

    handleProcess() {
      this.loading = this.$loading({
        lock: true,
        text: 'Loading',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      })
    },

    // 查看成功或者失败详情
    lookDetail(prop, tblRow) {
      // 查询组件数据
      let logIds
      if (prop === 'successNum') {
        this.lookTitle = '成功详情'
        logIds = tblRow.successIds
      } else {
        this.lookTitle = '失败详情'
        logIds = tblRow.failureIds
      }
      this.dialogVisible = true
      this.detailTblData = []
      getCompsByLogIds({ logIdStr: logIds.join(',') }).then(res => {
        const comps = res.data
        if (comps && comps.length > 0) {
          comps.forEach(item => {
            item['componentName'] = item.name
            this.detailTblData.push(item)
          })
        }
      }).catch(err => {
        console.error(err)
        this.$message.error('获取组件信息失败')
      })
    },

    // 日志详情
    logDetail(tblRow) {
      this.logVisible = true
      const logId = tblRow.buildHistoryId
      getBuildLogById({ logId: logId }).then(res => {
        const buildHistory = res.data
        if (buildHistory) {
          this.logContent = buildHistory.buildDesc
        }
      }).catch(err => {
        console.error(err)
        this.$message.error('获取构建日志失败')
      })
    },

    handleScroll({ scrollTop, scrollHeight }) {
      const wrapper = this.$refs.scrollbar.wrap
      this.autoScroll = scrollHeight - (scrollTop + wrapper.clientHeight) < 50
      this.scrollTop = scrollTop
      this.scrollHeight = scrollHeight
    },

    downloadTemplate() {
      this.$download('一键打包模板.xlsx')
    },

    handleSizeChange(val) {
      this.pageSize = val
      this.initOnePackData()
    },

    handleCurrentChange(val) {
      this.currentPage = val
      this.initOnePackData()
    }
  }
}
</script>

<style scoped>
#onekeypack {
  margin: 30px
}

#onekeypack /deep/ .headerClass {
  text-align: center;
}

#onekeypack /deep/ .cellClass {
  text-align: center;
  font-size: 14px;
}
.title-container {
  display: flex; /* 启用Flex布局 */
  justify-content: center; /* 水平居中所有子元素 */
  align-items: center; /* 垂直居中所有子元素 */
  gap: 10px; /* （可选）设置子元素之间的间距 */
}
.title-container .right-tag {
  margin-left: auto; /* 将标签推到最右侧 */
}
/* 可选：处理小屏幕下的换行问题 */
@media (max-width: 768px) {
  .title-container {
    flex-wrap: wrap; /* 允许子元素换行 */
  }
  .title-container .right-tag {
    margin-left: 0; /* 移除自动边距 */
    width: 100%; /* 让标签占满一行 */
    text-align: right; /* 标签内容右对齐 */
  }
}
</style>
